## 第05课 超声波模块

### （1）项目介绍：

![](media/image1.png)

HC-SR04超声波传感器像蝙蝠一样使用声纳来确定到物体的距离。 它提供出色的非接触范围检测，具有高精度和稳定的读数。 它带有超声波发射和接收模块。

HC-SR04或超声波传感器被广泛用于创建障碍物检测和距离测量应用以及其他各种应用的电子项目中。 在这里，我们介绍使用arduino和超声传感器测量距离的简单方法.

### （2）超声波参数：

电源：+ 5V DC

静态电流：<2mA

工作电流：15mA

有效角度：<15°

测距范围：2cm – 400 cm

分辨率：0.3厘米

测量角度：30度

触发输入脉冲宽度：10uS

### （3）项目组件：

| Keyes Uno Plus 开发板 红色环保*1 | Keyes brick L298P 电机驱动扩展板 V1*1 | keyes 草帽LED白发红模块*1 | HC-SR04超声波传感器*1 |
| --- | --- | --- | --- |
| <img src="media/image2.png" width="200"> | <img src="media/image3.png" width="200"> | <img src="media/image4.png" width="200"> | <img src="media/image5.png" width="200"> |
| HX-2.54 4P 双头 连接线*1 | 3Pin 双母头杜邦线*1 | USB线*1 | 18650双节电池盒*1<br />（电池 *2自配） |
| <img src="media/image7.png" width="200"> | <img src="media/image8.jpg" width="200"> | <img src="media/image9.png" width="200"> | <img src="media/image10.png" width="200"> |

### （4）超声波模块知识：

**原理：**看超声波的图可知，像是有两个眼睛，其一边是发射超声的，一边是接收超声波的，然后检测从发射遇到障碍物返回被接收到所需的时间**t**，再根据声音在空气中的传播速度大概是**343m/s, 距离 = 速度 * 时间**， 由于超声波发射返回是两段路程了，所以需要除以2，故超声波测到的** 距离 =（速度 * 时间）/2**

**超声波模块的使用方法及时序图：**

1、使用GPIO引脚给SR04的Trig引脚至少10μs的高电平信号，触发SR04模块测距功能；

2、触发后，模块会自动发送8个40KHz的超声波脉冲，并自动检测是否有信号返回。这步会由模块内部自动完成。

3、如有信号返回，Echo引脚会输出高电平，高电平持续的时间就是超声波从发射到返回的时间。

![](media/image12.png)

超声波模块的电路图

![](media/image13.png)

### （5）接线图：

  接线注意：超声波传感器模块的VCC引脚连接至keyestudio V5 传感器扩展板的5v(V)，Trig引脚至数字12(S)，Echo引脚至数字13(S)，Gnd引脚至Gnd(G)。

![](media/image14.png)

### （6）项目代码：

**示例代码 1（KE0165_5.1.ino）：**

```cpp
/*
  keyes 4WD 多功能智能车
  课程 5.1
  超声波传感器
  http://www.keyes-robot.com
*/

#define TRIG_PIN 12  // 触发引脚
#define ECHO_PIN 13  // 回声引脚

long duration, cm, inches;

/* 功能：初始化串口和引脚模式 */
void setup() {
  Serial.begin(9600);  // 初始化串口，波特率 9600
  pinMode(TRIG_PIN, OUTPUT);  // 设置触发引脚为输出
  pinMode(ECHO_PIN, INPUT);   // 设置回声引脚为输入
}

/* 功能：主循环，测量距离并输出 */
void loop() {
  digitalWrite(TRIG_PIN, LOW);  // 发送低电平脉冲，确保干净的高电平脉冲
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);  // 发送高电平脉冲，触发超声波
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);  // 结束触发脉冲

  duration = pulseIn(ECHO_PIN, HIGH);  // 读取回声脉冲持续时间（微秒）

  cm = (duration / 2) / 29.1;  // 计算距离（厘米）
  inches = (duration / 2) / 74;  // 计算距离（英寸）

  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();

  delay(200);  // 延时 200 毫秒
}
```


### （7）项目结果：

上传好测试代码到开发板，打开串口监视器，设置波特率为9600，我们可以看到超声波模块显示的距离，单位是厘米和英寸。用手阻挡超声波模块，我们看到显示距离的数值变小了。

![](media/image15.png)

### （8）代码说明:

**int trigPin-**这个是定义发射超声波的脚位，通常是输出， 

**int echoPin -** 这个是定义接收超声波的脚位，通常是输入。

**cm = (duration/2) / 29.1-**

**inches = (duration/2) / 74-**

我们可以使用以下公式计算距离：

距离=（行驶时间/ 2）x声速

声音速度为：343m / s = 0.0343 cm / uS = 1 / 29.1 cm / uS

或英寸：13503.9in / s = 0.0135in / uS = 1 / 74in / uS

我们需要将传播时间除以2，因为我们必须考虑到波浪已发送，撞击物体然后返回到传感器。

### （9）项目拓展：

我们刚刚测出了超声波显示的距离，那我们动动脑筋，能不能用测出的距离来做一些控制呢，如果控制一个LED灯的亮和灭。我们来试一下，在D9脚接上一个LED灯模块。

![](media/image16.png)

**示例代码 2（KE0165_5.2.ino）：**

```cpp
/*
  keyes 4WD 多功能智能车
  课程 5.2
  超声波传感器
  http://www.keyes-robot.com
*/

#define TRIG_PIN 12    // 触发引脚
#define ECHO_PIN 13    // 回声引脚
#define LED_PIN 9      // 指示灯引脚

long duration, cm, inches;

/* 功能：初始化串口及引脚模式 */
void setup() {
  Serial.begin(9600);           // 初始化串口通信
  pinMode(TRIG_PIN, OUTPUT);    // 设置触发引脚为输出
  pinMode(ECHO_PIN, INPUT);     // 设置回声引脚为输入
  pinMode(LED_PIN, OUTPUT);     // 设置指示灯引脚为输出
}

/* 功能：主循环，测距并控制指示灯 */
void loop() {
  digitalWrite(TRIG_PIN, LOW);           // 发送前先拉低触发引脚
  delayMicroseconds(2);                   // 延时确保干净的高电平脉冲
  digitalWrite(TRIG_PIN, HIGH);          // 发送高电平脉冲触发超声波
  delayMicroseconds(10);                  // 持续10微秒
  digitalWrite(TRIG_PIN, LOW);           

  duration = pulseIn(ECHO_PIN, HIGH);    // 读取回声引脚高电平持续时间（微秒）

  cm = (duration / 2) / 29.1;            // 计算距离（厘米）
  inches = (duration / 2) / 74;          // 计算距离（英寸）

  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();

  delay(50);                             // 延时50毫秒

  if (cm >= 2 && cm <= 10) {
    digitalWrite(LED_PIN, HIGH);        // 距离在2-10厘米范围内，点亮指示灯
  } else {
    digitalWrite(LED_PIN, LOW);         // 否则关闭指示灯
  }
}
```

上传好测试代码到开发板，我们用手去靠近超声波传感器，看LED 灯亮起来了没有。
